package com.ermax.aircond.manage.service;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ermax.aircond.common.domain.WriteMachineData;
import com.ermax.aircond.common.service.WriteMachineDataService;
import com.ermax.aircond.maintain.domain.Machine;
import com.ermax.aircond.manage.dao.ScheduleTermDao;
import com.ermax.aircond.manage.domain.ScheduleTerm;
import com.ermax.aircond.util.service.CalendarService;
import com.ermax.aircond.util.service.MachineCommandService;

@Service("scheduleControlService")
public class ScheduleControlService implements Serializable{

	private static final long serialVersionUID = 1L;
	
	@Resource(name = "scheduleTermDao")
	private ScheduleTermDao scheduleTermDao;
	@Resource(name="machineCommandService")
	private MachineCommandService machineCommandService;
	@Resource(name="writeMachineDataService")
	private WriteMachineDataService writeMachineDataService;

	@Resource(name="calendarService")
	private CalendarService calendarService;

	@Transactional(readOnly = true)
	public List<ScheduleTerm> getScheduleTerm(Machine machine) throws Exception{
		List<ScheduleTerm> scheduleTerms = scheduleTermDao.findScheduleTermByMachine(machine);
		Iterator<ScheduleTerm> iterator = scheduleTerms.iterator();
		while(iterator.hasNext()){
			ScheduleTerm scheduleTerm = iterator.next();
			scheduleTerm.setMachine(machine);
		}
		return scheduleTerms;
	}
	
	@Transactional(readOnly = true)
	public ScheduleTerm getScheduleTermById(long id) throws Exception{
		ScheduleTerm scheduleTerm = scheduleTermDao.getById(id);		
		return scheduleTerm;
	}
	
	@Transactional
	@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SUPERVISOR')")
	public void updateSchedule(ScheduleTerm scheduleTerm) throws Exception {
		//Reset last Execute date
		scheduleTerm.setLastExecuteTime(calendarService.getStartOfCalendarDate());
		scheduleTermDao.update(scheduleTerm);
	}
	
	@Transactional
	@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SUPERVISOR')")
	public void createSchedule(ScheduleTerm scheduleTerm) throws Exception{
		Machine machine = scheduleTerm.getMachine();
		
		short nid = machineCommandService.getShortNid(machine.getGateNo(), machine.getDeviceNo());
		scheduleTerm.setNid(nid);
		
		String cmd = convent(scheduleTerm);
		scheduleTerm.setCmd(cmd);
		
		scheduleTerm.setLastExecuteTime(calendarService.getStartOfCalendarDate());
		
		scheduleTermDao.create(scheduleTerm);
	}
	
	@Transactional
	@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_SUPERVISOR')")
	public void deleteSchedule(long id) throws Exception{				
		scheduleTermDao.deleteById(id);
	}
	
	private String convent(ScheduleTerm scheduleTerm){
		StringBuilder sb = new StringBuilder();
		
		sb.append(machineCommandService.getOnOffString(scheduleTerm.isStart()));		
		sb.append(machineCommandService.getFanSpeedString(scheduleTerm.getFanSpeed()));		
		sb.append(machineCommandService.getDefaultTempString(scheduleTerm.getTemperature()));		
		//sb.append(machineCommandService.getValveLevelString(scheduleTerm.getWindValue()));
		sb.append(machineCommandService.getKeyLockString(scheduleTerm.getKeyLock()));
		sb.append(machineCommandService.getMinimumTempString(scheduleTerm.getMinimumTemperature()));
		sb.append(machineCommandService.getValveOnOffString(1));
		
		return machineCommandService.getCommandString(sb.toString());
	}

	private List<ScheduleTerm> getScheduleToRun() {
		return scheduleTermDao.getScheduleToRun();
	}
	
	@Transactional
	public void runScheduleJob() {
		
		List<ScheduleTerm> scheduleTermList = getScheduleToRun();
		
		if (null != scheduleTermList && scheduleTermList.size() > 0) {
			for (ScheduleTerm scheduleTerm : scheduleTermList) {
				WriteMachineData writeMachineData = new WriteMachineData();
				writeMachineData.setNid(scheduleTerm.getNid());
				writeMachineData.setCmd(scheduleTerm.getCmd());
				
				//will change to batch update later
				writeMachineDataService.update(writeMachineData);				
				scheduleTermDao.updateScheduleExecutedTime(scheduleTerm);
				
				writeMachineDataService.flush();
			}
		}
		
	}
}
